<template>
  <div class="m-filter-item">
    <a-form ref="formRef" layout="inline" size="small" :model="formState">
      <a-form-item v-for="(item, index) in formConfig" :key="`filter-${index}`" :name="item.bindKey" class="form-item">
        <template v-slot:label>
          <span v-html="item.label"></span>
        </template>
        <a-input
          v-if="item.type === 'input'"
          v-model:value="formState[item.bindKey]"
          :bordered="false"
          tree-checkable
          allowClear
          size="small"
          :placeholder="item.placeholder || ''"
        />
        <a-tree-select
          v-if="item.type == 'tree'"
          size="small"
          v-model:value="formState[item.bindKey]"
          :default-value="item.default"
          :style="{ minWidth: '180px', maxWidth: '500px' }"
          :replace-fields="item.fieldNames"
          :dropdown-style="{ maxHeight: '320px', overflow: 'auto' }"
          :tree-data="item.options"
          :placeholder="item.placeholder || ''"
          @change="onSelectChange(item.change, $event)"
        >
          <template #title="{ cameraName }">
            {{ cameraName }}
          </template>
        </a-tree-select>
        <!-- <a-tree
          v-if="item.type == 'tree'"
          v-model:selectedKeys="formState[item.bindKey]"
          allow-clear
          multiple
          showIcon
          :style="{ minHeight: '100px', maxHeight: '300px', overflowY: 'scroll', postion: absolute }"
          :placeholder="item.placeholder || ''"
          :replace-fields="item.fieldNames"
          :tree-data="item.options"
          @check="checkHandle"
        >
          <template #video>
            <VideoCameraOutlined />
          </template>
          <template #organ>
            <ApartmentOutlined />
          </template>
        </a-tree> -->
        <a-select
          v-if="item.type === 'select'"
          v-model:value="formState[item.bindKey]"
          :allowClear="!item.allowClear"
          :mode="item.mode"
          :placeholder="item.placeholder || ''"
          :option-label-prop="item.optionLabelProp || 'label'"
          :show-arrow="defaultTrue(item.showArrow)"
          :showSearch="item.showSearch || null"
          size="small"
          @change="onSelectChange(item.change, $event)"
          class="w-180"
        >
          <a-select-option
            v-for="(opt, idx) in initSelectOptions(item.defaultOptions || item.options)"
            :key="`option-select-${item.bindKey}-${idx}`"
            :value="opt[selectInitField(item, 'value')]"
            :label="opt[selectInitField(item, 'name')]"
          >
            {{ opt[selectInitField(item, 'name')] }}
          </a-select-option>
        </a-select>
        <a-date-picker
          v-if="item.type === 'date'"
          allowClear
          type="date"
          showTime
          v-model:value="formState[item.bindKey]"
          :model="item.model || 'date'"
          size="small"
          valueFormat="YYYY-MM-DD HH:mm:ss"
          class="w-180"
        />
        <a-range-picker
          v-if="item.type === 'datetime'"
          :allowClear="!!item.allowClear"
          type="date"
          showTime
          v-model:value="formState[item.bindKey]"
          :model="item.model || 'datetime'"
          valueFormat="YYYY-MM-DD HH:mm:ss"
          :default-value="item.default"
          class="w-370"
          size="small"
          :disabled-date="disabledDate"
        />
        <a-cascader
          v-if="item.type === 'cascader'"
          v-model:value="formState[item.bindKey]"
          allowClear
          :defaultValue="item.defaultValue || []"
          :placeholder="item.placeholder || ''"
          :change-on-select="defaultTrue(item.changeOnSelect)"
          :field-names="item.fieldNames"
          :options="item.options"
          size="small"
          @change="onSelectChange(item.change, $event)"
        />
      </a-form-item>

      <a-form-item class="condition-query-buttons">
        <a-space size="small">
          <a-button
            v-for="(item, index) in btnConfig"
            :style="item.style || {}"
            :key="`button-${index}`"
            :type="item.type"
            v-show="defaultTrue(item.show)"
            size="small"
            @click="btnClick(item.clickType)"
          >
            {{ item.name }}
          </a-button>
        </a-space>
      </a-form-item>
    </a-form>
  </div>
</template>

<script lang="ts">
  import { defineComponent, reactive, ref, toRaw, UnwrapRef, watch } from 'vue'
  import { VideoCameraOutlined, ApartmentOutlined } from '@ant-design/icons-vue'
  export default defineComponent({
    name: 'filter-item',
    components: {
      VideoCameraOutlined,
      ApartmentOutlined
    },
    props: {
      formData: {
        type: Object,
        default() {
          return {}
        }
      },
      formConfig: {
        type: Array,
        default() {
          return []
        }
      },
      btnConfig: {
        type: Array,
        default() {
          return []
        }
      }
    },
    setup(props: any, ctx: any) {
      const $emit = ctx.emit
      const formRef = ref()
      const formState: UnwrapRef<any> = reactive(JSON.parse(JSON.stringify(props.formData)))
      const btnConfigList: any[] = toRaw(props.btnConfig)
      const formConfigList: any[] = toRaw(props.formConfig)
      let result: any
      const resultView = ref(result)
      const showTree = ref(false)
      /** @name watch */
      watch(
        () => props.formData,
        (val) => {
          Object.assign(formState, val)
        },
        { deep: true }
      )

      /** @name computed */

      /** @name methods */
      /** @description 初始化select选项数据结构 */
      const initSelectOptions = function (options: Array<any>) {
        if (!options || !options.length) {
          return options
        }
        if (typeof options[0] === 'string') {
          return options.map((item) => {
            return {
              name: item,
              value: item
            }
          })
        }
        return options
      }
      /** @description 重定义select fieldNames */
      const selectInitField = function (item: any, type: string) {
        if (item.fieldNames) {
          return item.fieldNames[type]
        }
        return type
      }
      /** @description 定义select事件监听 */
      const onSelectChange = function (changeCallback: any, value: any) {
        if (!changeCallback) {
          return
        }
        if (typeof changeCallback !== 'function') {
          throw new TypeError('params:change must be a function')
        }
        changeCallback(value)
        // 2022年02月18日11:57:17 TODO
        // const resetKey = changeCallback(value)
        // if (this.copyData[resetKey]) {
        //   this.copyData[resetKey] = ''
        // }
      }
      // 查询时注入处理结果的函数并获取相应的结果
      const injectCustomValueRule = (type: string, key: string, value: any) => {
        let ret: any
        formConfigList.forEach((item: any) => {
          // console.log(item.bindKey, 'key', key)
          if (item.bindKey === key && item.customRender) {
            ret = item.customRender(value)
          }
          // reset操作，清空defaultOptions的选项
          if (type === 'reset' && item.defaultOptions) {
            item.defaultOptions = []
          }
        })
        return ret
      }
      const interceptResult = () => {
        const ret = JSON.parse(JSON.stringify(formState))
        return ret
      }
      const defaultTrue = (bool: any): boolean => {
        return bool !== false
      }
      const reset = () => {
        formRef.value.resetFields()
      }
      const btnClick = (type: string, watch = false): void => {
        const params: any = {}
        if (type === 'reset') {
          reset()
        }
        formConfigList.forEach((item: any) => {
          result = interceptResult()
          resultView.value = result
          const key = item.bindKey
          let value = result[key] === undefined ? '' : result[key]
          if (type === 'reset' && (item.type === 'cascader' || item.type === 'tree')) {
            value = []
            formState[key] = []
          }
          // 判断是否注入了自定义函数
          const customValue: any = injectCustomValueRule(type, key, value)
          if (typeof customValue === 'function') {
            customValue({ key, value, params })
          } else if (customValue === null) {
            // 返回值为null 此字段不会添加到返回结果中
          } else if (customValue !== undefined) {
            params[key] = customValue
          } else {
            params[key] = value
          }
        })
        if (watch) {
          $emit('change', { type, params })
        } else {
          $emit('btnClick', { type, params })
        }
      }

      const checkHandle = (value, option) => {
        option.checkedNodes.forEach((item) => {
          console.log(item.props.title)
        })
      }

      const treeToArray = (arr, keys) => {
        const data = JSON.parse(JSON.stringify(arr))
        const newData: any = []
        const callback = (item) => {
          (item.children || (item.children = [])).map(v => {
            callback(v)
          })
          delete item.children
          newData.push(item)
        }
        data.map((v) => callback(v))
        const names: any = []
        newData.forEach((item) => {
          if (keys.join(',').indexOf(item.cameraId) > -1) {
            names.push(item.organizationName)
          }
        })
        return names
      }

      return {
        formConfigList,
        btnConfigList,
        formState,
        formRef,
        result,
        resultView,
        copyWatching: true,
        btnClick,
        defaultTrue,
        showTree,
        // select
        initSelectOptions,
        selectInitField,
        onSelectChange,
        // export
        reset,
        checkHandle,
        treeToArray,
        disabledDate: (current) => {
          return current > new Date()
        }
      }
    }
  })
</script>
<style lang="less" scoped>
  .m-filter-item {
    display: flex;
    align-items: center;
    background: #f2f2f2;
    padding: 2px 10px;
  }
  :deep(.ant-form-item) {
    display: flex;
    align-items: center;
    margin-bottom: 6px;
    margin-top: 6px;
  }
  .form-item {
    :deep(.ant-form-item-control-input) {
      box-shadow: 0 0 10px rgba(179, 192, 231, 0.4);
      border-radius: 4px;
    }
  }
  :deep(.ant-select:not(.ant-select-customize-input) .ant-select-selector) {
    border: 0 transparent;
  }
  :deep(.ant-calendar-picker-input.ant-input) {
    border: 0 transparent;
  }
  .w-370 {
    width: 370px !important;
  }
  :deep(.ant-form-item-label) {
    font-weight: 600;
    color: #333;
  }
</style>
